home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / opsprd.zip / OPSPREAD.PAS < prev    next >
Pascal/Delphi Source File  |  1992-10-19  |  19KB  |  596 lines

  1. {$R-,S-,I-,V-,B-,F+,O+,A-}
  2.  
  3. {Conditional defines that may affect this unit}
  4. {$I OPDEFINE.INC}
  5.  
  6. {*********************************************************}
  7. {*                   OPSPREAD.PAS 1.20                   *}
  8. {*        Copyright (c) TurboPower Software 1992.        *}
  9. {*                 All rights reserved.                  *}
  10. {*********************************************************}
  11.  
  12. unit OpSpread;
  13.   {-Spreadsheet-like pick lists}
  14.  
  15. interface
  16.  
  17. uses
  18.   OpInline,
  19.   OpString,
  20.   OpConst, {!!.20}
  21.   OpRoot,
  22.   OpCrt,
  23.   {$IFDEF UseMouse}
  24.   OpMouse,
  25.   {$ENDIF}
  26.   OpCmd,
  27.   OpFrame,
  28.   OpWindow,
  29.   {$IFDEF UseDrag}
  30.   OpDrag,
  31.   {$ENDIF}
  32.   OpPick;
  33.  
  34. const
  35.   {---- Orientation code for a SpreadList ----}
  36.   pkSpread          = 4;
  37.  
  38.   {---- Stream codes for a SpreadList ----}
  39.   otSpreadList      = 998;
  40.   veSpreadList      = 0;
  41.   ptPickSpread      = 998;
  42.  
  43. type
  44.   SpreadListPtr = ^SpreadList;
  45.   SpreadList =
  46.     object(PickList)
  47.       slRows : Word;
  48.       slCols : Word;
  49.  
  50.       constructor Init(X1, Y1, X2, Y2 : Byte;
  51.                        ItemWidth : Byte;
  52.                        NumRows : Word;
  53.                        NumCols : Word;
  54.                        StringProc : pkStringProc;
  55.                        CommandHandler : pkGenlProc);
  56.         {-Initialize a spreadsheet list}
  57.       constructor InitCustom(X1, Y1, X2, Y2 : Byte;
  58.                              var Colors : ColorSet;
  59.                              Options : LongInt;
  60.                              ItemWidth : Byte;
  61.                              NumRows : Word;
  62.                              NumCols : Word;
  63.                              StringProc : pkStringProc;
  64.                              CommandHandler : pkGenlProc);
  65.         {-Initialize a spreadsheet list with custom window options}
  66.       constructor InitAbstract(X1, Y1, X2, Y2 : Byte;
  67.                                var Colors : ColorSet;
  68.                                Options : LongInt;
  69.                                ItemWidth : Byte;
  70.                                NumRows : Word;
  71.                                NumCols : Word;
  72.                                CommandHandler : pkGenlProc);
  73.          {-Constructor to be called by derived types that override
  74.            the ItemString method}
  75.       constructor InitDeluxe(X1, Y1, X2, Y2 : Byte;
  76.                              var Colors : ColorSet;
  77.                              Options : LongInt;
  78.                              ItemWidth : Byte;
  79.                              NumRows : Word;
  80.                              NumCols : Word;
  81.                              StringProc : pkStringProc;
  82.                              CommandHandler : pkGenlProc;
  83.                              PickOptions : Word);
  84.         {-Initialize a spread list with custom window and pick options}
  85.       constructor InitAbstractDeluxe(X1, Y1, X2, Y2 : Byte;
  86.                                      var Colors : ColorSet;
  87.                                      Options : LongInt;
  88.                                      ItemWidth : Byte;
  89.                                      NumRows : Word;
  90.                                      NumCols : Word;
  91.                                      CommandHandler : pkGenlProc;
  92.                                      PickOptions : Word);
  93.          {-Constructor to be called by derived types that override the
  94.            ItemString method, with custom pick options}
  95.  
  96.       function GetItemRow(Item : Word) : Word;
  97.         {-Return the absolute row position of the item}
  98.       function GetItemCol(Item : Word) : Word;
  99.         {-Return the absolute column position of the item}
  100.       function GetItemNum(Row, Col : Word) : Word;
  101.         {-Return the item number corresponding to Row and Col}
  102.       procedure TopLeftRowCol(var Row, Col : Word);
  103.         {-Return the Row and Col of the top left item}
  104.  
  105.       {-These routines generate an error in a SpreadList}
  106.       procedure ChangeNumItems(NumItems : Word);
  107.         {-Change the number of items to display}
  108.       procedure ChangeOrientation(Orientation : pkGenlProc);
  109.         {-Change the orientation}
  110.  
  111.     {$IFDEF UseStreams}
  112.       constructor Load(var S : IdStream);
  113.         {-Load a spread list from a stream}
  114.       procedure Store(var S : IdStream);
  115.         {-Store a spread list in a stream}
  116.     {$ENDIF}
  117.  
  118.       {++++ for internal use ++++}
  119.       {.Z+}
  120.       procedure pkInitPickSize1; virtual;
  121.       function pkProcessCursorCommand(var Cmd : Word) : Boolean; virtual;
  122.       {.Z-}
  123.     end;
  124.  
  125. {$IFDEF UseStreams}
  126.   {---- Stream registration ----}
  127.   procedure SpreadListStream(SPtr : IdStreamPtr);
  128.     {-Register all types needed for streams containing spread lists}
  129. {$ENDIF}
  130.  
  131.   {.Z+}
  132.   {---- Orientation routine used for spread lists ----}
  133.   procedure PickSpread(P : PickListPtr);
  134.     {-Orientation initialization for spreadsheet-like picklists}
  135.   {.Z-}
  136.  
  137.   {====================================================================}
  138.  
  139. implementation
  140.  
  141. function GetSpread(First, Row, Col : Word; P : PickListPtr) : Word;
  142.   {-Get item number given <First, Row, Col>}
  143. begin
  144.   with SpreadListPtr(P)^ do
  145.     GetSpread := First+(Col-1)+(Row-1)*slCols;
  146. end;
  147.  
  148. procedure SetSpread(Choice, First : Word; P : PickListPtr);
  149.   {-Set valid <pkFirst, pkRow, pkCol> given Choice and First}
  150. var
  151.   FirstRow : Word;
  152.   FirstCol : Word;
  153. begin
  154.   with SpreadListPtr(P)^ do begin
  155.     pkChoice := Choice;
  156.     pkFirst := First;
  157.     pkCommonValidation;
  158.  
  159.     {Force pkFirst into a valid range}
  160.     FirstRow := GetItemRow(pkFirst);
  161.     if FirstRow+pkHeight-1 > pkItemRows then begin
  162.       dec(pkFirst, (FirstRow+pkHeight-1-pkItemRows)*slCols);
  163.       FirstRow := GetItemRow(pkFirst);
  164.     end;
  165.     FirstCol := GetItemCol(pkFirst);
  166.     if FirstCol+pkCols-1 > slCols then begin
  167.       dec(pkFirst, FirstCol+pkCols-1-slCols);
  168.       FirstCol := GetItemCol(pkFirst);
  169.     end;
  170.  
  171.     {Assure pkFirst is in a range to make pkChoice visible}
  172.     {And compute row and column}
  173.     pkRow := GetItemRow(pkChoice)-FirstRow+1;
  174.     if pkRow > pkHeight then begin
  175.       inc(pkFirst, (pkRow-pkHeight)*slCols);
  176.       pkRow := pkHeight;
  177.     end;
  178.     pkCol := GetItemCol(pkChoice)-FirstCol+1;
  179.     if pkCol > pkCols then begin
  180.       inc(pkFirst, pkCol-pkCols);
  181.       pkCol := pkCols;
  182.     end;
  183.   end;
  184. end;
  185.  
  186. procedure ReinitSpread(P : PickListPtr);
  187.   {-Reinitialize some fields based on width, height and orientation}
  188. var
  189.   MaxRow : Word;
  190.   MaxCol : Word;
  191. begin
  192.   with SpreadListPtr(P)^ do begin
  193.     {pkMaxFirst controls how much scrolling, if any, is possible}
  194.     pkMaxFirst := (pkItemRows-pkHeight)*slCols+(slCols-pkCols+1);
  195.  
  196.     {Amount to change pkFirst by when scrolling (not used)}
  197.     pkScroll := 1;
  198.  
  199.     {$IFDEF UseScrollBars}
  200.     {Set up for scroll bars}
  201.     ChangeAllScrollBars(1, slCols, 1, pkItemRows);
  202.     {$ENDIF}
  203.   end;
  204. end;
  205.  
  206. {$IFDEF UseScrollBars}
  207. procedure UpdScrollSpread(P : PickListPtr);
  208.   {-Update scroll bars}
  209. begin
  210.   with SpreadListPtr(P)^ do
  211.     DrawAllSliders(GetItemCol(pkFirst)+pkCol-1, GetItemRow(pkFirst)+pkRow-1);
  212. end;
  213.  
  214. procedure SetScrollSpread(FramePos : FramePosType;
  215.                           MPosX, MPosY : Byte;
  216.                           UserVal : LongInt; P : PickListPtr);
  217.   {-Set pick position based on slider position}
  218. var
  219.   FirstRow : Word;
  220.   FirstCol : Word;
  221. begin
  222.   with SpreadListPtr(P)^ do begin
  223.     case FramePos of
  224.       frLL, frRR :   {Vertical scroll bar}
  225.         begin
  226.           UserVal := TweakSlider(FramePos, MPosY, UserVal, 1);
  227.           FirstRow := GetItemRow(pkFirst);
  228.           if UserVal < FirstRow then begin
  229.             dec(pkFirst, (FirstRow-UserVal)*slCols);
  230.             FirstRow := UserVal;
  231.           end else if UserVal > FirstRow+pkHeight-1 then begin
  232.             inc(pkFirst, (UserVal-FirstRow-pkHeight+1)*slCols);
  233.             inc(FirstRow, UserVal-FirstRow-pkHeight+1);
  234.           end;
  235.           pkRow := UserVal-FirstRow+1;
  236.         end;
  237.     else {Horizontal scroll bar}
  238.       UserVal := TweakSlider(FramePos, MPosX, UserVal, 1);
  239.       FirstCol := GetItemCol(pkFirst);
  240.       if UserVal < FirstCol then begin
  241.         dec(pkFirst, FirstCol-UserVal);
  242.         FirstCol := UserVal;
  243.       end else if UserVal > FirstCol+pkCols-1 then begin
  244.         inc(pkFirst, UserVal-FirstCol-pkCols+1);
  245.         FirstCol := UserVal-pkCols+1;
  246.       end;
  247.       pkCol := UserVal-FirstCol+1;
  248.     end;
  249.  
  250.     pkChoice := pkGetCurrent(pkFirst, pkRow, pkCol, P);
  251.   end;
  252. end;
  253. {$ENDIF}
  254.  
  255. function ScrolledSpread(pChoice, pFirst : Word; pRow, pCol : Byte;
  256.                         P : PickListPtr) : Boolean;
  257.   {-Perform a one-element optimized scroll if possible}
  258. begin
  259.   with SpreadListPtr(P)^ do begin
  260.     ScrolledSpread := True;
  261.     if pFirst+slCols = pkFirst then
  262.       pkScrollDown(pChoice, pRow, pCol)
  263.     else if pkFirst+slCols = pFirst then
  264.       pkScrollUp(pChoice, pRow, pCol)
  265.     else if pFirst+1 = pkFirst then
  266.       pkScrollRight(pChoice, pRow, pCol)
  267.     else if pkFirst+1 = pFirst then
  268.       pkScrollLeft(pChoice, pRow, pCol)
  269.     else
  270.       ScrolledSpread := False;
  271.   end;
  272. end;
  273.  
  274. procedure PickSpread(P : PickListPtr);
  275.   {-Orientation initialization for spreadsheet-like picklists}
  276. begin
  277.   with SpreadListPtr(P)^ do begin
  278.     pkOrient := pkSpread;
  279.     pkGetCurrent := GetSpread;
  280.     pkSetCurrent := SetSpread;
  281.     pkReinit := ReinitSpread;
  282.     {$IFDEF UseScrollBars}
  283.     pkUpdScrBar := UpdScrollSpread;
  284.     pkSetScroll := SetScrollSpread;
  285.     {$ENDIF}
  286.     pkScrolled := ScrolledSpread;
  287.   end;
  288. end;
  289.  
  290. function SpreadList.GetItemRow(Item : Word) : Word;
  291. begin
  292.   GetItemRow := (Item+slCols-1) div slCols;
  293. end;
  294.  
  295. function SpreadList.GetItemCol(Item : Word) : Word;
  296. begin
  297.   GetItemCol := ((Item-1) mod slCols)+1;
  298. end;
  299.  
  300. function SpreadList.GetItemNum(Row, Col : Word) : Word;
  301. begin
  302.   GetItemNum := (Row-1)*slCols+Col;
  303. end;
  304.  
  305. procedure SpreadList.TopLeftRowCol(var Row, Col : Word);
  306. begin
  307.   Row := GetItemRow(pkFirst);
  308.   Col := GetItemCol(pkFirst);
  309. end;
  310.  
  311. procedure SpreadList.pkInitPickSize1; {virtual;}
  312. var
  313.   Wid : Byte;
  314. begin
  315.   if pkReqdWidth > pkWidth then
  316.     {Clip width as required by window size}
  317.     pkItemWidth := pkWidth
  318.   else
  319.     pkItemWidth := pkReqdWidth;
  320.  
  321.   {Compute number of columns of items, and number of items in each column}
  322.   if pkDividers then
  323.     Wid := pkWidth+1
  324.   else
  325.     Wid := pkWidth;
  326.   pkCols := Wid div pkItemWidth;
  327.   pkItemRows := slRows;
  328.  
  329.   {Limit rows as appropriate}
  330.   if pkItemRows < 1 then
  331.     pkItemRows := 1;
  332.   if pkHeight > pkMaxRows then
  333.     pkHeight := pkMaxRows;
  334.   if pkHeight > pkItemRows then
  335.     pkHeight := pkItemRows;
  336. end;
  337.  
  338. function SpreadList.pkProcessCursorCommand(var Cmd : Word) : Boolean; {virtual;}
  339. var
  340.   Row : Word;
  341.   Bot : Word;
  342.   Col : Word;
  343. begin
  344.   pkProcessCursorCommand := False;
  345.   case Cmd of
  346.     ccNone :                   {Nothing}
  347.       Exit;
  348.  
  349.     ccUp :                     {Up}
  350.       if pkRow > 1 then
  351.         Dec(pkRow)
  352.       else begin
  353.         Row := GetItemRow(pkFirst);
  354.         if FlagIsSet(pkFlags, pkExitAtEdges) and (Row = 1) then begin
  355.           Cmd := ccExitAtTop;
  356.           pkProcessCursorCommand := True;
  357.         end else if (Row > 1) then
  358.           dec(pkFirst, slCols);
  359.       end;
  360.  
  361.     ccDown :                   {Down}
  362.       if pkRow < pkHeight then
  363.         Inc(pkRow)
  364.       else begin
  365.         Row := GetItemRow(pkFirst);
  366.         if FlagIsSet(pkFlags, pkExitAtEdges) and (Row = pkItemRows-pkHeight+1) then begin
  367.           Cmd := ccExitAtBot;
  368.           pkProcessCursorCommand := True;
  369.         end else if (Row < pkItemRows-pkHeight+1) then
  370.           inc(pkFirst, slCols);
  371.       end;
  372.  
  373.     ccLeft :                   {Left}
  374.       if pkCol > 1 then
  375.         Dec(pkCol)
  376.       else begin
  377.         Col := GetItemCol(pkFirst);
  378.         if FlagIsSet(pkFlags, pkExitAtEdges) and (Col = 1) then begin
  379.           Cmd := ccExitLeft;
  380.           pkProcessCursorCommand := True;
  381.         end else if Col > 1 then
  382.           dec(pkFirst);
  383.       end;
  384.  
  385.     ccRight :                  {Right}
  386.       if pkCol < pkCols then
  387.         Inc(pkCol)
  388.       else begin
  389.         Col := GetItemCol(pkFirst);
  390.         if FlagIsSet(pkFlags, pkExitAtEdges) and (Col = slCols-pkCols+1) then begin
  391.           Cmd := ccExitRight;
  392.           pkProcessCursorCommand := True;
  393.         end else if Col < slCols-pkCols+1 then
  394.           inc(pkFirst);
  395.       end;
  396.  
  397.     ccPageUp :                 {PgUp}
  398.       begin
  399.         Row := GetItemRow(pkFirst);
  400.         if Row > pkHeight then
  401.           dec(pkFirst, slCols*pkHeight)
  402.         else if Row = 1 then
  403.           pkRow := 1
  404.         else
  405.           dec(pkFirst, slCols*(Row-1));
  406.       end;
  407.  
  408.     ccPageDn :                 {PgDn}
  409.       begin
  410.         Row := GetItemRow(pkFirst);
  411.         Bot := Row+pkHeight-1;
  412.         if Bot+pkHeight <= pkItemRows then
  413.           inc(pkFirst, slCols*pkHeight)
  414.         else if Bot = pkItemRows then
  415.           pkRow := pkHeight
  416.         else
  417.           inc(pkFirst, slCols*(pkItemRows-Bot));
  418.       end;
  419.  
  420.     ccHome :                   {Left of row}
  421.       begin
  422.         pkFirst := pkFirst-((pkFirst-1) mod slCols);
  423.         pkCol := 1;
  424.       end;
  425.  
  426.     ccEnd :                    {Right of row}
  427.       begin
  428.         pkFirst := pkFirst-((pkFirst-1) mod slCols)+slCols-pkCols;
  429.         pkCol := pkCols;
  430.       end;
  431.  
  432.     ccTopOfFile :              {Top of sheet}
  433.       begin
  434.         pkFirst := pkFirst mod slCols;
  435.         pkRow := 1;
  436.       end;
  437.  
  438.     ccEndOfFile :              {End of sheet}
  439.       begin
  440.         pkFirst := (pkFirst mod slCols)+slCols*(pkItemRows-pkHeight);
  441.         pkRow := pkHeight;
  442.       end;
  443.  
  444.   end;
  445.   pkChoice := pkGetCurrent(pkFirst, pkRow, pkCol, @Self);
  446. end;
  447.  
  448. constructor SpreadList.Init(X1, Y1, X2, Y2 : Byte;
  449.                             ItemWidth : Byte;
  450.                             NumRows : Word;
  451.                             NumCols : Word;
  452.                             StringProc : pkStringProc;
  453.                             CommandHandler : pkGenlProc);
  454. begin
  455.   if not SpreadList.InitDeluxe(X1, Y1, X2, Y2,
  456.                                DefaultColorSet,
  457.                                DefWindowOptions,
  458.                                ItemWidth, NumRows, NumCols,
  459.                                StringProc, CommandHandler,
  460.                                DefPickOptions) then
  461.     Fail;
  462. end;
  463.  
  464. constructor SpreadList.InitCustom(X1, Y1, X2, Y2 : Byte;
  465.                                   var Colors : ColorSet;
  466.                                   Options : LongInt;
  467.                                   ItemWidth : Byte;
  468.                                   NumRows : Word;
  469.                                   NumCols : Word;
  470.                                   StringProc : pkStringProc;
  471.                                   CommandHandler : pkGenlProc);
  472. begin
  473.   if not SpreadList.InitDeluxe(X1, Y1, X2, Y2,
  474.                                Colors,
  475.                                Options,
  476.                                ItemWidth, NumRows, NumCols,
  477.                                StringProc, CommandHandler,
  478.                                DefPickOptions) then
  479.     Fail;
  480. end;
  481.  
  482. constructor SpreadList.InitAbstract(X1, Y1, X2, Y2 : Byte;
  483.                                     var Colors : ColorSet;
  484.                                     Options : LongInt;
  485.                                     ItemWidth : Byte;
  486.                                     NumRows : Word;
  487.                                     NumCols : Word;
  488.                                     CommandHandler : pkGenlProc);
  489. begin
  490.  if not SpreadList.InitAbstractDeluxe(X1, Y1, X2, Y2,
  491.                                       Colors, Options,
  492.                                       ItemWidth, NumRows, NumCols,
  493.                                       CommandHandler,
  494.                                       DefPickOptions) then
  495.     Fail;
  496. end;
  497.  
  498. constructor SpreadList.InitDeluxe(X1, Y1, X2, Y2 : Byte;
  499.                                   var Colors : ColorSet;
  500.                                   Options : LongInt;
  501.                                   ItemWidth : Byte;
  502.                                   NumRows : Word;
  503.                                   NumCols : Word;
  504.                                   StringProc : pkStringProc;
  505.                                   CommandHandler : pkGenlProc;
  506.                                   PickOptions : Word);
  507. var
  508.   NumItems : LongInt;
  509. begin
  510.   {Validate the number of items}
  511.   NumItems := LongInt(NumRows)*NumCols;
  512.   if (NumItems = 0) or (NumItems > 65535) then begin
  513.     InitStatus := epFatal+ecBadParam;
  514.     Fail;
  515.   end;
  516.  
  517.   {Save the rows and columns}
  518.   slRows := NumRows;
  519.   slCols := NumCols;
  520.  
  521.   {Initialize it}
  522.   if not PickList.InitDeluxe(X1, Y1, X2, Y2, Colors, Options, ItemWidth,
  523.                              NumItems, StringProc, PickSpread,
  524.                              CommandHandler, PickOptions) then
  525.     Fail;
  526. end;
  527.  
  528. constructor SpreadList.InitAbstractDeluxe(X1, Y1, X2, Y2 : Byte;
  529.                                           var Colors : ColorSet;
  530.                                           Options : LongInt;
  531.                                           ItemWidth : Byte;
  532.                                           NumRows : Word;
  533.                                           NumCols : Word;
  534.                                           CommandHandler : pkGenlProc;
  535.                                           PickOptions : Word);
  536. begin
  537.   if not SpreadList.InitDeluxe(X1, Y1, X2, Y2,
  538.                                Colors, Options,
  539.                                ItemWidth, NumRows, NumCols,
  540.                                NoPickString,
  541.                                CommandHandler, DefPickOptions) then
  542.     Fail;
  543. end;
  544.  
  545. procedure SpreadList.ChangeNumItems(NumItems : Word);
  546. begin
  547.   RunError(211);
  548. end;
  549.  
  550. procedure SpreadList.ChangeOrientation(Orientation : pkGenlProc);
  551. begin
  552.   RunError(211);
  553. end;
  554.  
  555. {$IFDEF UseStreams}
  556. constructor SpreadList.Load(var S : IdStream);
  557. begin
  558.   if not PickList.Load(S) then
  559.     Fail;
  560.   S.Read(slRows, 2*SizeOf(Word));
  561.   if S.PeekStatus <> 0 then begin
  562.     Done;
  563.     Fail;
  564.   end;
  565. end;
  566.  
  567. procedure SpreadList.Store(var S : IdStream);
  568. begin
  569.   {Store the underlying pick list}
  570.   PickList.Store(S);
  571.   if S.PeekStatus <> 0 then
  572.     Exit;
  573.  
  574.   {Store what's unique to the spread list}
  575.   S.Write(slRows, 2*SizeOf(Word));
  576. end;
  577.  
  578. procedure SpreadListStream(SPtr : IdStreamPtr);
  579. begin
  580.   with SPtr^ do begin
  581.     PickListStream(SPtr);
  582.     RegisterType(otSpreadList, veSpreadList, TypeOf(SpreadList),
  583.                  @SpreadList.Store, @SpreadList.Load);
  584.  
  585.     {Register the orientation routine, since there's only one}
  586.     RegisterPointer(ptPickSpread, @PickSpread);
  587.   end;
  588. end;
  589. {$ENDIF}
  590.  
  591.  
  592. {$IFDEF InitAllUnits}
  593. begin
  594. {$ENDIF}
  595. end.
  596.